//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#include "ippIP.h"
#include "ccamera.h"

#define _ALIGN4(adr) ((((Ipp32u)(adr))+3)&(~3))
void *  __cdecl memcpy(void *, const void *, size_t);

EXTERN_C unsigned long *g_pMmxData;
static unsigned int s_dummyFlag = 0x3; // Let all WMMX registers be saved.
EXTERN_C void SaveWMMXRegisters(ulong_t *pMmxData, uint_t *pFlags);
EXTERN_C void RestoreWMMXRegisters(ulong_t *pMmxData);

EXTERN_C IppStatus ASM_ippiYCbCr422RszRot_8u_P3R(const Ipp8u *pSrc[3],
                int srcStep[3], IppiSize srcSize, Ipp8u *pDst[3],
                int dstStep[3], IppiSize dstSize,
                IppCameraInterpolation interpolation,
                IppCameraRotation rotation, int rcpRatiox, int rcpRatioy);

EXTERN_C ECode IppYCbCr422ResizeCopy(
                unsigned char * pYSrc, unsigned char * pCbSrc,
                unsigned char * pCrSrc, unsigned char * pYDst,
                unsigned char * pCbDst, unsigned char * pCrDst,
                int srcWidth, int srcHeight,
                int dstWidth, int dstHeight)
{
    // RIGHT CODE, USING IPP
    Ipp8u *p8uDst[3];
    IppiSize srcSize, dstSize;
    IppCameraRotation rotation;
    IppCameraInterpolation interpolation;
    int rcpRatioX, rcpRatioY;
    int srcStep[3], dstStep[3];
    int status = ippStsNoErr;

    int w2;
    int h2;
    int w3;
    int h3;

    Ipp8u *p8uSrc[3];

//    DBGOUT(cprintf("IppResizeCopy: dstWidth = %d, dstHeight = %d, "
//        "pSrc->width = %d, pSrc->height = %d\n",
//        dstWidth, dstHeight, srcWidth, srcHeight));
    if (dstWidth <= 0 || dstHeight <= 0) {
        return E_INVALID_ARGUMENT;
    }

    /* Initialize parameters */
    w2 = ((srcWidth + 1) >> 1);
    h2 = ((srcHeight + 1) >> 0);
    w3 = ((dstWidth + 1) >> 1);
    h3 = ((dstHeight + 1) >> 0);

    srcSize.width = srcWidth;
    srcSize.height = srcHeight;
    dstSize.width = dstHeight; // NOTICE
    dstSize.height = dstWidth; // NOTICE

    srcStep[0] = srcWidth;
    srcStep[1] = w2;
    srcStep[2] = w2;
    dstStep[0] = dstWidth;
    dstStep[1] = w3;
    dstStep[2] = w3;

    interpolation = ippCameraInterpNearearest;//  ippCameraInterpBilinear;
    rotation = ippCameraRotate90R; // ippCameraRotateDisable;

    rcpRatioX =
        (int)((((srcSize.width-1)<<16))/ (dstSize.width - 1));
    rcpRatioY =
        (int)((((srcSize.height-1)<<16)) / (dstSize.height - 1));

//    DBGOUT(cprintf("IppResizeCopy: rcpRatioX = %d, rcpRatioY = %d\n",
//        rcpRatioX, rcpRatioY));

    p8uSrc[0] = (Ipp8u*)pYSrc,
    p8uSrc[1] = (Ipp8u*)pCbSrc,
    p8uSrc[2] = (Ipp8u*)pCrSrc;

    p8uDst[0] = (Ipp8u*)_ALIGN4(pYDst),
    p8uDst[1] = (Ipp8u*)pCbDst,
    p8uDst[2] = (Ipp8u*)pCrDst;

    // This function is invoked in ISR now, and it will changed WMMX registers
    // (in ipp call), so the current WMMX registers should be saved.
    // Save current WMMX registers:
    SaveWMMXRegisters(g_pMmxData, &s_dummyFlag);

    /* resize & rotate */
    status = ASM_ippiYCbCr422RszRot_8u_P3R(
        (const unsigned char **)p8uSrc, srcStep, srcSize, p8uDst, dstStep, dstSize,
        interpolation, rotation, rcpRatioX, rcpRatioY);
//    DBGOUT(cprintf("IppResizeCopy: status = %d\n", status));

    // Load saved WMMX registers:
    RestoreWMMXRegisters(g_pMmxData);

    return NOERROR;
}
